using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Threading;
using System.IO;
using System.Collections;
using System.ComponentModel;


namespace Lizk.SimpleHUD
{
    public class HUDEngine : HUDContainerSimple
    {
        private HUDRenderer renderer;
#if !XBOX
        [Browsable(false)]
#endif

        public HUDRenderer Renderer
        {
            get { return renderer; }
            set { renderer = value; }
        }

        public HUDEngine(HUDRenderer renderer)
        {
            this.renderer = renderer;
        }

        public void PaintContainer(int cAlpha, RectangleS parentRect, RectangleS canvas, HUDControl cont)
        {
            if (!(cont is ICollection))
                return;


            RectangleS contPos = new RectangleS(parentRect.X + cont.Bounds.X, parentRect.Y + cont.Bounds.Y, cont.Bounds.Width, cont.Bounds.Height);
            RectangleS paintArea = RectangleS.Intersect(canvas, contPos);
            if (paintArea == RectangleS.Empty)
                return;

            int a = (int)((float)cAlpha * ((float)cont.Alpha / 255f));

            if (a <= 0)
                return;

            renderer.EnterContainer(paintArea);

            foreach (HUDControl gc in (ICollection)cont)
            {
                if (!gc.Visible)
                    continue;
                if (gc is ICollection)
                {
                    PaintContainer(a, contPos, paintArea, gc);
                }
                else if (gc is HUDLabel)
                {
                    HUDLabel gl = (HUDLabel)gc;
                    if (string.IsNullOrEmpty(gl.Font))
                    {
                        continue;
                    }
                    if (!renderer.HasFont(HUDFont.GetFont(gl.Font)))
                    {
                        renderer.LoadFont(HUDFont.GetFont(gl.Font));
                    }
                    PaintText2(a, contPos, paintArea, gl);
                }
                else if (gc is HUDVideo2)
                {

                    HUDVideo2 gi = (HUDVideo2)gc;
                    if (string.IsNullOrEmpty(gi.SourceUrl))
                        continue;

                    if (!renderer.VideoLoaded(gi))
                    {
                        renderer.LoadVideo(gi);
                    }

                    PaintVideo(a, contPos, paintArea, gi);
                }
                else if (gc is HUDImage)
                {
                    
                    HUDImage gi = (HUDImage)gc;
                    if (gi.File == null)
                        continue;

                    if (gi.ReloadImage)
                    {
                        renderer.UnloadImage(gi);
                        renderer.LoadImage(gi);
                    }
                    gi.ReloadImage = false;
                    if (!renderer.ImageLoaded(gi))
                    {
                        renderer.LoadImage(gi);
                    }

                    PaintImage(a, contPos, paintArea, gi);
                }
            }
            renderer.LeaveContainer(paintArea);
        }

        private void PaintVideo(int cAlpha, RectangleS parentRect, RectangleS canvas, HUDVideo2 gi)
        {
            RectangleS imagePos = new RectangleS(parentRect.X + gi.Bounds.X, parentRect.Y + gi.Bounds.Y, gi.Bounds.Width, gi.Bounds.Height);
            RectangleS paintArea = RectangleS.Intersect(canvas, imagePos);
            int a = (int)((float)cAlpha * ((float)gi.Alpha / 255f));

            if (a <= 0)
                return;

            if (paintArea == RectangleS.Empty)
                return;

            RectangleS srcRect = new RectangleS();

            RectangleS imageStuff = HUDImage.ResizeConstrained(gi.ConstrainProportions, gi.SourceSize, gi.Size);
            imageStuff.X += gi.Bounds.X;
            imageStuff.Y += gi.Bounds.Y;

            imagePos = new RectangleS(parentRect.X + imageStuff.X, parentRect.Y + imageStuff.Y, imageStuff.Width, imageStuff.Height);
            paintArea = RectangleS.Intersect(canvas, imagePos);

            RectangleS test = new RectangleS((imagePos.X - paintArea.X) / imageStuff.Width * gi.SourceSize.Width, (imagePos.Y - paintArea.Y) / imageStuff.Height * gi.SourceSize.Height, (paintArea.Width / imageStuff.Width) * gi.SourceSize.Width, (paintArea.Height / imageStuff.Height) * gi.SourceSize.Height);

            srcRect = new RectangleS(test.X * -1, test.Y * -1, test.Width, test.Height);

            renderer.PaintVideo(paintArea, srcRect, (byte)a, gi);
        }

        private void PaintImage(int cAlpha, RectangleS parentRect, RectangleS canvas, HUDImage gi)
        {
            if (!renderer.ImageLoaded(gi))
                return;

            RectangleS imagePos = new RectangleS(parentRect.X + gi.Bounds.X, parentRect.Y + gi.Bounds.Y, gi.Bounds.Width, gi.Bounds.Height);
            RectangleS paintArea = RectangleS.Intersect(canvas, imagePos);
            int a = (int)((float)cAlpha * ((float)gi.Alpha / 255f));

            if (a <= 0)
                return;

            if (paintArea == RectangleS.Empty)
                return;

            RectangleS srcRect = new RectangleS();

            RectangleS imageStuff = HUDImage.ResizeConstrained(gi.ConstrainProportions, gi.ImageSize.Size, gi.Size);
            imageStuff.X += gi.Bounds.X;
            imageStuff.Y += gi.Bounds.Y;

            imagePos = new RectangleS(parentRect.X + imageStuff.X, parentRect.Y + imageStuff.Y, imageStuff.Width, imageStuff.Height);
            paintArea = RectangleS.Intersect(canvas, imagePos);

            RectangleS test = new RectangleS((imagePos.X - paintArea.X) / imageStuff.Width * gi.ImageSize.Width, (imagePos.Y - paintArea.Y) / imageStuff.Height * gi.ImageSize.Height, (paintArea.Width / imageStuff.Width) * gi.ImageSize.Width, (paintArea.Height / imageStuff.Height) * gi.ImageSize.Height);

            srcRect = new RectangleS(test.X * -1, test.Y * -1, test.Width, test.Height);

            renderer.PaintImage(paintArea, srcRect, (byte)a, gi);
        }

        private void PaintText2(int cAlpha, RectangleS parentRect, RectangleS canvas, HUDLabel label)
        {
            RectangleS dest = new RectangleS(parentRect.X + label.Bounds.X, parentRect.Y + label.Bounds.Y, label.Bounds.Width, label.Bounds.Height);
            RectangleS r = RectangleS.Intersect(canvas, dest);
            int a = (int)((float)cAlpha * ((float)label.Alpha / 255f));

            if (a <= 0)
                return;

            if (r == RectangleS.Empty)
                return;

            PointS adjusted = new PointS(r.X - dest.X, r.Y - dest.Y);
            SizeS adjustedSize = new SizeS(r.Width, r.Height);


            renderer.PaintText(r, new RectangleS(adjusted, adjustedSize), (byte)a, label, 0);
        }
    }
}
